﻿// Learn more about F# at http://fsharp.net

module AnnotateMe.Library

open AnnotateMe.Interfaces
open System.Drawing
open System.Drawing.Text

type Label = string
type Connector =
    | Line

type Effect =
    | ColoredBox of Color

type Annotation = Effect*Connector*Label

type Block =
    | AnnotatedBlock of Label*Annotation
    | NonAnnotatedBlock of Label

type AnnotaionTask = { Blocks : seq<Block>; Font : Font; AnnotationFont : Font; } 

let draw (task : AnnotaionTask)  (gr : Graphics) =
   let blockList = task.Blocks |> Seq.toList;
   let startX = 50.0f;
   let startY = 100.0f;
   let font = task.Font;
   let annotationFont = task.AnnotationFont;
   use blackBrush = new SolidBrush(Color.Black);
   use blackPen = new Pen(Color.Black);
   let spaceWidth = gr.MeasureString(" ", font).Width;

   let rec drawBlock blockslist (gr : Graphics) (X:float32) (Y:float32) rectangles =
      match blockslist with
      | [] -> ()
      | head::tail ->
        match head with
            | AnnotatedBlock (label, (ColoredBox(effectColor), Line, annotationLabel))  ->
                //draw label
                let labelSize = gr.MeasureString(label, font);
                gr.DrawString (label, font, blackBrush, X, Y);
                
                //draw rectangle
                let rect = new Rectangle((int)X, (int)Y, (int)labelSize.Width, (int)labelSize.Height);
                use pen = new Pen(effectColor, 2.0f);
                use brush = new SolidBrush(Color.FromArgb(30, effectColor));
                gr.DrawRectangle(pen, rect);
                gr.FillRectangle(brush, rect);

                //determine connector length
                let annotationLabelSize = gr.MeasureString(annotationLabel, annotationFont);
                let halfAnnotationWidth = annotationLabelSize.Width / 2.0f;
                let middlePointX = X + labelSize.Width/2.0f
                let possibleLengths = seq { for i in 1..100 do yield (float32)(i)*10.0f }
                let connectorLength = possibleLengths |> Seq.find (fun l ->  
                        let possibleAnnotationRectangle = new Rectangle((int)(middlePointX - halfAnnotationWidth), (int)(Y - l - annotationLabelSize.Height), (int)annotationLabelSize.Width, (int)annotationLabelSize.Height);
                        not (rectangles |> List.exists possibleAnnotationRectangle.IntersectsWith))

                //draw connector
                gr.DrawLine(blackPen, middlePointX, Y, middlePointX, Y - connectorLength);
                
                //draw annotation label
                gr.DrawString(annotationLabel, annotationFont, blackBrush, middlePointX - halfAnnotationWidth, Y - connectorLength - annotationLabelSize.Height);

                let annotationRectangle = new Rectangle((int)(middlePointX - halfAnnotationWidth), (int)(Y - connectorLength - annotationLabelSize.Height), (int)annotationLabelSize.Width, (int)annotationLabelSize.Height);

                drawBlock tail gr (X + labelSize.Width + spaceWidth) Y (annotationRectangle :: rectangles)
            | NonAnnotatedBlock (label) -> 
                let labelWidth = gr.MeasureString(label, font).Width;
                gr.DrawString (label, font, blackBrush, X, Y);
                drawBlock tail gr (X + labelWidth + spaceWidth) Y rectangles     

   drawBlock blockList gr startX startY []



